/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package fr.eisti.icc.data.controller;

import java.io.Serializable;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import fr.eisti.icc.data.Document;
import fr.eisti.icc.data.controller.exceptions.NonexistentEntityException;
import fr.eisti.icc.data.controller.exceptions.RollbackFailureException;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.transaction.UserTransaction;

/**
 *
 * @author clion
 */
public class DocumentJpaController implements Serializable {

    public DocumentJpaController(UserTransaction utx, EntityManagerFactory emf) {
        this.utx = utx;
        this.emf = emf;
    }
    private UserTransaction utx = null;
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Document document) throws RollbackFailureException, Exception {
        if (document.getDocsALireAvant() == null) {
            document.setDocsALireAvant(new ArrayList<Document>());
        }
        EntityManager em = null;
        try {
            utx.begin();
            em = getEntityManager();
            List<Document> attachedDocsALireAvant = new ArrayList<Document>();
            for (Document docsALireAvantDocumentToAttach : document.getDocsALireAvant()) {
                docsALireAvantDocumentToAttach = em.getReference(docsALireAvantDocumentToAttach.getClass(), docsALireAvantDocumentToAttach.getId());
                attachedDocsALireAvant.add(docsALireAvantDocumentToAttach);
            }
            document.setDocsALireAvant(attachedDocsALireAvant);
            em.persist(document);
            for (Document docsALireAvantDocument : document.getDocsALireAvant()) {
                docsALireAvantDocument.getDocsALireAvant().add(document);
                docsALireAvantDocument = em.merge(docsALireAvantDocument);
            }
            utx.commit();
        } catch (Exception ex) {
            try {
                utx.rollback();
            } catch (Exception re) {
                throw new RollbackFailureException("An error occurred attempting to roll back the transaction.", re);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Document document) throws NonexistentEntityException, RollbackFailureException, Exception {
        EntityManager em = null;
        try {
            utx.begin();
            em = getEntityManager();
            Document persistentDocument = em.find(Document.class, document.getId());
            List<Document> docsALireAvantOld = persistentDocument.getDocsALireAvant();
            List<Document> docsALireAvantNew = document.getDocsALireAvant();
            List<Document> attachedDocsALireAvantNew = new ArrayList<Document>();
            for (Document docsALireAvantNewDocumentToAttach : docsALireAvantNew) {
                docsALireAvantNewDocumentToAttach = em.getReference(docsALireAvantNewDocumentToAttach.getClass(), docsALireAvantNewDocumentToAttach.getId());
                attachedDocsALireAvantNew.add(docsALireAvantNewDocumentToAttach);
            }
            docsALireAvantNew = attachedDocsALireAvantNew;
            document.setDocsALireAvant(docsALireAvantNew);
            document = em.merge(document);
            for (Document docsALireAvantOldDocument : docsALireAvantOld) {
                if (!docsALireAvantNew.contains(docsALireAvantOldDocument)) {
                    docsALireAvantOldDocument.getDocsALireAvant().remove(document);
                    docsALireAvantOldDocument = em.merge(docsALireAvantOldDocument);
                }
            }
            for (Document docsALireAvantNewDocument : docsALireAvantNew) {
                if (!docsALireAvantOld.contains(docsALireAvantNewDocument)) {
                    docsALireAvantNewDocument.getDocsALireAvant().add(document);
                    docsALireAvantNewDocument = em.merge(docsALireAvantNewDocument);
                }
            }
            utx.commit();
        } catch (Exception ex) {
            try {
                utx.rollback();
            } catch (Exception re) {
                throw new RollbackFailureException("An error occurred attempting to roll back the transaction.", re);
            }
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                int id = document.getId();
                if (findDocument(id) == null) {
                    throw new NonexistentEntityException("The document with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(int id) throws NonexistentEntityException, RollbackFailureException, Exception {
        EntityManager em = null;
        try {
            utx.begin();
            em = getEntityManager();
            Document document;
            try {
                document = em.getReference(Document.class, id);
                document.getId();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The document with id " + id + " no longer exists.", enfe);
            }
            List<Document> docsALireAvant = document.getDocsALireAvant();
            for (Document docsALireAvantDocument : docsALireAvant) {
                docsALireAvantDocument.getDocsALireAvant().remove(document);
                docsALireAvantDocument = em.merge(docsALireAvantDocument);
            }
            em.remove(document);
            utx.commit();
        } catch (Exception ex) {
            try {
                utx.rollback();
            } catch (Exception re) {
                throw new RollbackFailureException("An error occurred attempting to roll back the transaction.", re);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Document> findDocumentEntities() {
        return findDocumentEntities(true, -1, -1);
    }

    public List<Document> findDocumentEntities(int maxResults, int firstResult) {
        return findDocumentEntities(false, maxResults, firstResult);
    }

    private List<Document> findDocumentEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Document.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Document findDocument(int id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Document.class, id);
        } finally {
            em.close();
        }
    }

    public int getDocumentCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Document> rt = cq.from(Document.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
    
}
